import {
  CubeReflectionMapping,
  CubeRefractionMapping,
  EquirectangularReflectionMapping,
  EquirectangularRefractionMapping,
} from '../../constants.js';
import { WebGLCubeRenderTarget } from '../WebGLCubeRenderTarget.js';

function WebGLCubeMaps(renderer) {
  let cubemaps = new WeakMap();

  function mapTextureMapping(texture, mapping) {
    if (mapping === EquirectangularReflectionMapping) {
      texture.mapping = CubeReflectionMapping;
    } else if (mapping === EquirectangularRefractionMapping) {
      texture.mapping = CubeRefractionMapping;
    }

    return texture;
  }

  function get(texture) {
    if (texture && texture.isTexture) {
      const mapping = texture.mapping;

      if (mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping) {
        if (cubemaps.has(texture)) {
          const cubemap = cubemaps.get(texture).texture;
          return mapTextureMapping(cubemap, texture.mapping);
        } else {
          const image = texture.image;

          if (image && image.height > 0) {
            const currentRenderTarget = renderer.getRenderTarget();

            const renderTarget = new WebGLCubeRenderTarget(image.height / 2);
            renderTarget.fromEquirectangularTexture(renderer, texture);
            cubemaps.set(texture, renderTarget);

            renderer.setRenderTarget(currentRenderTarget);

            texture.addEventListener('dispose', onTextureDispose);

            return mapTextureMapping(renderTarget.texture, texture.mapping);
          } else {
            // image not yet ready. try the conversion next frame

            return null;
          }
        }
      }
    }

    return texture;
  }

  function onTextureDispose(event) {
    const texture = event.target;

    texture.removeEventListener('dispose', onTextureDispose);

    const cubemap = cubemaps.get(texture);

    if (cubemap !== undefined) {
      cubemaps.delete(texture);
      cubemap.dispose();
    }
  }

  function dispose() {
    cubemaps = new WeakMap();
  }

  return {
    get,
    dispose,
  };
}

export { WebGLCubeMaps };
